///\todo upgrade

//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2011 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#ifndef _BUOLA_IO_CMEMMAP_H_
#define _BUOLA_IO_CMEMMAP_H_

#include <buola/io/cfd.h>

namespace buola { namespace io {

/////////////////////////////////////////////////////////////////////////////////////////////////

/// memory mapping (base class)

/// Represents the mapping of a (part of a) file or shared-memory segment into the address space
/// of the process.
///
/////////////////////////////////////////////////////////////////////////////////////////////////

class CMemMap : public UUncopiable
{
protected:
    /// leaves the mapping uninitialized
    
    /// Must be mapped before it is used.
    explicit CMemMap(void *pAddress=nullptr,std::size_t pSize=0)
        :   mAddress(pAddress)
        ,   mSize(pSize)
    {}
    
    ///move constructor
    CMemMap(CMemMap &&pRH)
        :   mAddress(pRH.mAddress)
        ,   mSize(pRH.mSize)
    {}
    
    /// destructor
    
    /// Protected to make sure that derived objects aren't destructed through the (non-virtual) base destructor
    ~CMemMap()=default;
    
    void *GetAddress() const     {   return mAddress;    }
    std::size_t GetSize() const  {   return mSize;       }

protected:
    void *mAddress;
    std::size_t mSize;
};
  
/////////////////////////////////////////////////////////////////////////////////////////////////

/// shared memory mapping

/// Represents the mapping of a (part of a) shared-memory segment into the address space
/// of the process.
///
/////////////////////////////////////////////////////////////////////////////////////////////////

class CShmMap : public CMemMap
{
private:
    /// initializes the mapping
    
    /// Can only be called from CShmHandle
    CShmMap(void *pAddress,std::size_t pSize,std::ptrdiff_t pExtraOffset)
        :   CMemMap(pAddress,pSize)
        ,   mExtraOffset(pExtraOffset)
    {
    }
    
public:
    /// move constructor
    
    /// It is the constructor which will usually be used, to construct objects with mappings returned by
    /// CShmHandle::Map()
    CShmMap(CShmMap &&pRH)
        :   CMemMap(std::move(pRH))
        ,   mExtraOffset(pRH.mExtraOffset)
    {}
    
    ~CShmMap()
    {
        Close();
    }

    void Close()
    {
        if(mAddress)
        {
            CFD::Unmap(static_cast<char*>(mAddress)-mExtraOffset,mSize+mExtraOffset);
            mAddress=nullptr;
        }
    }
    
    CShmMap &operator=(CShmMap &&pRH)
    {
        swap(pRH);
        return *this;
    }

private:
    std::ptrdiff_t mExtraOffset;
    
    friend class CShmHandle;
};
  
/*namespace io*/ } /*namespace buola*/ }

#endif
